<?php
/**
 * IDAR查询对象
 *
 * @package util.dar
 * @version $Id: IDarQuery.php 312 2008-04-23 16:29:38Z iwind $
 * @since 0.0.3
 */
class IDarQuery  extends IObject {
	private $condition;
	private $orders = array();
	private $offset = 0;
	private $size = 0; 
	
	const ORDER_ASC = "ASC";
	const ORDER_DESC = "DESC";
	const MAX_ROWS = 2147483648;
	
	private $parameters = array();
	
	/**
	 * 构造
	 *
	 * @since 0.0.3
	 */
	public function __construct() {
		
	}
	
	/**
	 * 生成查询对象
	 * 
	 * $query = array(
	 * 		"offset"=>1,
	 * 		"size"=>10,
	 * 		"orders"=>array("Blog", "id"),
	 * 		"condition"=>"[Blog.category]=:categoryId"
	 * 		"parameters"=>array("categoryId"=>1)
	 * );
	 * 
	 * 从0.1.1开始，可以使用cond代替condition，params代替parameters，如果两者同时存在，则全称优先级比简称高
	 * 
	 * 从0.1.1开始，可以使用conds表示一组条件，而且cond和conds可以同时使用
	 * 
	 * 从0.2开始，可以使用order参数，设置依照单个字段排序
	 *
	 * @param array $query 查询描述数组 
	 * @return IDarQuery
	 * @since 0.1
	 */
	public static function create(array $query = null) {
		$darQuery = new IDarQuery();
		if ($query != null) {			
			$map = new IAssocMap($query);
			if ($map->containsKey("offset")) {
				$darQuery->setOffset($map->get("offset"));
			}
			if ($map->containsKey("size")) {
				$darQuery->setSize($map->get("size"));
			}
			
			//orders
			if ($map->containsKey("orders")) {
				$orders = $map->get("orders");
				if (!is_array($orders)) {
					throw new IDarException("orders should be an array");
				}
				$darQuery->setOrders($orders);
			}
			
			//order
			if ($map->containsKey("order")) {
				$order = $map->get("order");
				$darQuery->addOrderByArray($order);
			}
			
			//condition
			if ($map->containsKey("cond")) {
				$darQuery->setCondition($map->get("cond"));
			}
			
			if ($map->containsKey("condition")) {
				$darQuery->setCondition($map->get("condition"));
			}
			
			//conds
			if ($map->containsKey("conds")) {
				$conds = $map->get("conds");
				if (is_array($conds) && !empty($conds)) {
					$_conds = implode(" AND ", $conds);
					$condition = trim($darQuery->getCondition());
					if ($condition == "") {
						$darQuery->setCondition($_conds);
					}
					else {
						$darQuery->setCondition("(" . $condition . ") AND (" . $_conds . ")");
					}
				}
			}
			
			//parameters
			if ($map->containsKey("params")) {
				$params = $map->get("params");
				if (!is_array($params)) {
					throw new IDarException("params should be an array");
				}
				$darQuery->setParameters($params);
			}
			
			if ($map->containsKey("parameters")) {
				$params = $map->get("parameters");
				if (!is_array($params)) {
					throw new IDarException("parameters should be an array");
				}
				$darQuery->setParameters($params);
			}
		}
		return $darQuery;
	}
	
	/**
	 * 设置条件
	 *
	 * @param string $conditionString 条件语句
	 * @return IDarQuery
	 * @since 0.0.3
	 */
	public function setCondition($conditionString) {
		$this->condition = trim($conditionString);
		return $this;
	}
	
	/**
	 * 设置排序字段
	 * 
	 * $orders = array(array("model"=>"Log", "field"=>"id", "order"=>IDarQuery::ORDER_DESC), ... );//多字段排序
	 * $orders = array("model"=>"Log", "field"=>"id", "order"=>IDarQuery::ORDER_DESC);//单字段排序
	 *
	 * @param array $orders 需要排序的字段描述
	 * @return IDarQuery
	 * @since 0.0.3
	 */
	public function setOrders(array $orders) {
		$newOrders = array();
		$singleOrder = array();
		foreach ($orders as $key => $order) {
			if (!is_array($order)) {
				$singleOrder[$key] = $order;
			}
			else {
				if (!array_key_exists("model", $order) && !array_key_exists("field", $order) && !array_key_exists("order", $order)) {
					$order["model"] = (isset($order[0]))?$order[0]:null;
					$order["field"] = (isset($order[1]))?$order[1]:null;
					$order["order"] = (isset($order[2]))?$order[2]:null;
					$newOrders[$key] = $order;
				}
				$newOrders[$key] = $order;
			}
		}
		if (!empty($singleOrder)) {
			if (!array_key_exists("model", $singleOrder) && !array_key_exists("field", $singleOrder) && !array_key_exists("order", $singleOrder)) {
					$singleOrder["model"] = (isset($singleOrder[0]))?$singleOrder[0]:null;
					$singleOrder["field"] = (isset($singleOrder[1]))?$singleOrder[1]:null;
					$singleOrder["order"] = (isset($singleOrder[2]))?$singleOrder[2]:null;
			}
			$newOrders[] = $singleOrder;
		}
		$this->orders = $newOrders;
		return $this;
	}
	
	/**
	 * 添加排序字段
	 *
	 * @param string $model 模型名
	 * @param string $fieldName 字段名
	 * @param string $order 排序类型
	 * @return IDarQuery
	 * @since 0.0.3
	 */
	public function addOrder($model, $fieldName, $order = self::ORDER_ASC) {
		$this->orders[] = array("model"=>$model, "field"=>$fieldName, "order"=>$order);
		return $this;
	}
	
	/**
	 * 添加排序字段
	 *
	 * @param array $orderArray 排序说明
	 * @return IDarQuery
	 * @since 0.2
	 */
	public function addOrderByArray($orderArray) {
		$model = null;
		$field = null;
		$order = null;
		if (!is_array($orderArray)) {
			throw new IDarException("IDarQuery order must be an array");
		}
		if (array_key_exists("model", $orderArray)) {
			$model = $orderArray["model"];
		}
		if (array_key_exists("field", $orderArray)) {
			$field = $orderArray["field"];
		}
		if (array_key_exists("order", $orderArray)) {
			$order = $orderArray["order"];
		}
		if (is_null($model) && is_null($field)) {
			if (isset($orderArray[0])) $model = $orderArray[0];
			if (isset($orderArray[1])) $field = $orderArray[1];
			if (isset($orderArray[2])) $order = $orderArray[2];
		}
		if (!is_null($model) && !is_null($field)) {
			$this->addOrder($model, $field, $order);
			return $this;
		}
		throw new IDarException("IDarQuery order must define model and field");
	}
	
	/**
	 * 设置起始行数
	 *
	 * @param integer $offset 起始行
	 * @return IDarQuery
	 * @since 0.0.3
	 */
	public function setOffset($offset) {
		$this->offset = intval($offset);
		if ($this->offset < 0) {
			throw new IDarException("IDarQuery offset can't small than 0");
		}
		return $this;
	}
	
	/**
	 * 设置查询行数
	 *
	 * @param integer $size 查询行数
	 * @return IDarQuery
	 * @since 0.0.3
	 */
	public function setSize($size) {
		$this->size = intval($size);
		if ($this->size < -1) {
			throw new IDarException("IDarQuery size can't small than -1");
		}
		if ($this->size == -1) {
			$this->size = self::MAX_ROWS;
		}
		return $this;
	}
	
	/**
	 * 取得查询条件
	 *
	 * @return string
	 * @since 0.0.3
	 */
	public function getCondition() {
		return trim($this->condition);
	}
	
	/**
	 * 取得排序
	 *
	 * @return array
	 * @since 0.0.3
	 */
	public function getOrders() {
		return $this->orders;
	}
	
	/**
	 * 取得起始行数
	 *
	 * @return integer
	 * @since 0.0.3
	 */
	public function getOffset() {
		return $this->offset;
	}
	
	/**
	 * 取得查询行数
	 *
	 * @return integer
	 * @since 0.0.3
	 */
	public function getSize() {
		return $this->size;
	}
	
	/**
	 * 取得排序类型列表
	 *
	 * @return array
	 * @since 0.0.3
	 */
	public static function getOrderTypes() {
		return array(self::ORDER_ASC , self::ORDER_DESC);
	}
	
	/**
	 * 设置参数集
	 *
	 * @param array $parameters 参数集
	 * @return IDarQuery
	 * @since 0.0.3
	 */
	public function setParameters(array $parameters) {
		$this->parameters = $parameters;
		return $this;
	}
	
	/**
	 * 添加参数
	 *
	 * @param string|integer $name 参数名
	 * @param mixed $value 参数值
	 * @return IDarQuery
	 * @since 0.1
	 */
	public function addParameter($name, $value) {
		$this->parameters[$name] = $value;
		return $this;
	}
	
	/**
	 * 取得参数集
	 *
	 * @return array
	 * @since 0.0.3
	 */
	public function getParameters() {
		return $this->parameters;
	}
}

?>